package com.jiesone.logger.distributecleaning.handler;
/*
 *@ClassName LoggerDistrbuteRedisReceiver
 *@Description TODO
 *@Author tangsixiang@163.com
 *@Date 2022/1/18 15:12
 *@Version 1.0
 */

import com.alibaba.fastjson.JSON;
import com.jiesone.logger.distributecleaning.config.CommonRediskey;
import com.jiesone.logger.distributecleaning.entity.SplittingIntegral;
import com.jiesone.logger.distributecleaning.service.LoggerMachingService;
import com.jiesone.logger.distributecleaning.util.ElasticSearchUtil;
import com.jiesone.logger.distributecleaning.util.JsonStringUtil;
import com.jiesone.logger.distributecleaning.util.SnowFlake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class ResolveLogDataRedisHandler {



    Logger logger= LoggerFactory.getLogger(ResolveLogDataRedisHandler.class);
    private CountDownLatch latch;

    @Autowired
    JdbcTemplate  jdbcTemplate;

    @Autowired
    SnowFlake snowFlake;

    @Autowired
    public ResolveLogDataRedisHandler(CountDownLatch latch) {
        this.latch = latch;
    }


    @Value("${logger-filebeat.analyticalChannel}")
    private String analyticalChannel;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    ElasticSearchUtil searchUtil;


    @Autowired
    LoggerMachingService machingService;
    /**
     * 需要加工数据清切分格式化数据 程业务处理
     * @param message
     */
    public void receiverMessage(String  message) {

        logger.info("==----订阅Redis消息通道内容："+message);
        Map<String,Object> datamap= JSON.parseObject(message, HashMap.class);

        String sourceCode=datamap.get("sourceCode").toString();
         //根据业务Code 获取清洗数据规则

        String  logData=datamap.get("message").toString();
            //判断走智能切分流程

             String  targetStr=      stringRedisTemplate.opsForHash().get(CommonRediskey.savaTarget,sourceCode+":0").toString();
                   Map<String,Object> tarData=  JSON.parseObject(targetStr, HashMap.class) ;
                   if(tarData.get("targetType").equals(0)&& analyticalChannel.equals("line") ){
                       logger.info("-------自定义解析字符业务中---------");
                       String indexName=tarData.get("targetIndex").toString();
                       //用户自定义模式解析字符串  业务判断流程
                          customLoggerData(sourceCode,logData,0,indexName);
                       //智能业务判断  字符串
                         intelligenceLoggerData(sourceCode,logData,1,indexName);

                   }else  if(analyticalChannel.equals("column")){


                    logger.info("--------colum解析数据-------------------"+datamap);

                        ranksSplittingIntegral(sourceCode,tarData.get("targetIndex").toString().toLowerCase(),logData, new LinkedHashMap<>());

                   }

    }


    /**
     * 智能解析字符串 进行业务处理
     * @param sourceCode
     * @param message
     * @param type
     */
     public     void  intelligenceLoggerData(String sourceCode,String message,int  type,String indexName){
        String  zhiRule=String.format(CommonRediskey.dataRuleSet,sourceCode,type);
         boolean zhiSource=stringRedisTemplate.hasKey(zhiRule);
         Map<String,Object>  indexData=new HashMap<>();
         if(zhiSource){
             Iterator<String>  set=stringRedisTemplate.opsForSet().members(zhiRule).iterator();
              while (set.hasNext()){
                 Map<String,Object>  ruleDesc= JSON.parseObject(set.next(),HashMap.class);

                    this.stringChanage(ruleDesc,indexData,message);
              }

         }
            if(indexData.size()>=1){
                try {
                    indexData.put("timestamp",System.currentTimeMillis());
                    searchUtil.insertOrUpdateOne(indexName,indexData);





                } catch (Exception e) {
                    e.printStackTrace();
                }
                logger.info("实际中解析到目标文本：------------分隔符|拆分符-------------");

            }
            }





        public   void  customLoggerData(String sourceCode,String message,int  type,String indexName){
            //自定义切分数据流程

            String  zhiRule=String.format(CommonRediskey.dataRuleSet,sourceCode,type);
            boolean ziSource=stringRedisTemplate.hasKey(zhiRule);
            Map<String,Object>  indexData=new HashMap<>();
            if(ziSource){
                Iterator<String> it = stringRedisTemplate.opsForSet().members(zhiRule).iterator();
                while (it.hasNext()){
                    Map<String,Object>  ruleDesc= JSON.parseObject(it.next(),HashMap.class);
                    this.stringChanage(ruleDesc,indexData,message);
                }
            }
            if(indexData.size()>=1){
                try {
                    indexData.put("timestamp",System.currentTimeMillis());//追加入库标准时间
                    long  snowId=snowFlake.nextId();
                    searchUtil.insertOrUpdateOne(indexName,snowId,indexData);
                    /*********************加工后数据*****************************/
                      //获取日志等级字段值
                    logAlarmNotification(0,indexData.get("level").toString(), indexName, sourceCode, snowId);



                } catch (Exception e) {
                    e.printStackTrace();
                }
                logger.info("实际中解析到目标日志：正则表达式中-------------完成业务清洗");
            }



        }


    /**
     *
     * @param sourceMap   配置解析字符串 封装对象
     * @param indexMap   存储数据目标数据封装集合
     */
    public   void  stringChanage(Map<String,Object> sourceMap,Map<String,Object> indexMap,String message){
            Object  ruleformat=sourceMap.get("ruleFormat");
        if(ruleformat.equals("INTER")){   //字符串截取
            //截取目标字符串 标识符
             int   charIndex=(Integer)  sourceMap.getOrDefault("charIndex",0);//获取截取下标
            int   charEnd=(Integer)  sourceMap.getOrDefault("charIndex",0);//获取截取下标
               int   ruleIndex=   message.indexOf(sourceMap.get("rulePretty").toString());
                  //赋值给目标字符串截取后
                    if(charIndex==-1){
                        message= message.substring(ruleIndex+sourceMap.get("rulePretty").toString().length());
                    }else{
                        message=ruleIndex>charIndex? message.substring(charIndex,ruleIndex):message.substring(ruleIndex+sourceMap.get("rulePretty").toString().length(),charIndex);
                    }

                   if(sourceMap.containsKey("ruleKeyDesc")){

                       String[] keyStr=   sourceMap.get("ruleKeyDesc").toString().split(";");
                             for (String str:keyStr){
                                 String keyName=  str.split("=")[0];
                                 indexMap.put(keyName,message);
                             }
                    }

        }else if(ruleformat.equals("SEPAR")){  //分隔符解析
             String[]   mesStr=      message.split(sourceMap.get("rulePretty").toString());
            if(sourceMap.containsKey("ruleKeyDesc")){

                String[] keyStr=   sourceMap.get("ruleKeyDesc").toString().split(";");
                int i=0;
                for (String str:keyStr){
                    String keyName=  str.split("=")[0];
                    int valueIndex= Integer.parseInt(str.split("=")[1]);
                    if(valueIndex< mesStr.length){
                        indexMap.put(keyName,mesStr[valueIndex]);
                    }
                }
            }
        }else if(ruleformat.equals("JSON")){
            if(JsonStringUtil.isCheckJSON(message)){
                Map mesMap = JSON.parseObject(message, HashMap.class);






                 indexMap.putAll(mesMap);
            }
        }else  if(ruleformat.equals("NOR")){
            //正则表达式 形式解析字符串

                //   sourceMap.get("rulePretty");
            //获取正则表达式内容
            Pattern p =   Pattern.compile(sourceMap.get("rulePretty").toString());
                     Matcher m=   p.matcher(message);

                      int valueNum=m.groupCount();

                       if(valueNum>=1){
                           if(sourceMap.containsKey("ruleKeyDesc")){

                               String[] keyStr=   sourceMap.get("ruleKeyDesc").toString().split(";");


                               for (String str:keyStr){
                                   String keyName=  str.split("=")[0] ;
                                   int valueIndex= Integer.parseInt(str.split("=")[1]);
                                   if(valueIndex<m.groupCount()){
                                       indexMap.put(keyName,m.group(valueIndex));
                                   }

                               }
                           }

                       }


        }





        }



    public  boolean   logAlarmNotification(int  alarmType,String level,String indexName,String sourceCode,Long snowId){
        logger.debug("=========根据设置的告警规则生产符合要求告警信息============");
        String alarmKey=sourceCode+":"+alarmType;
        String key=CommonRediskey.aleamRule;

        if(stringRedisTemplate.opsForHash().hasKey(key, alarmKey)&&JsonStringUtil.checkLevel(stringRedisTemplate.opsForHash().get(key,alarmKey).toString(),level)){

            return  jdbcTemplate.update(
                    "INSERT INTO `loger_alarm_ruledesc` (`desc_id`,`alarm_type`,`alarm_level`,`index_name`,`source_code`,`query_value`)VALUE(?,?,?,?,?,?)"
                    ,snowFlake.nextId(),alarmType,level,indexName,sourceCode,snowId)>0;

        }
        return  false;
    }


    /**
     *   此业务方法  智能切分业务处理流程   通过表字段列 匹配相对应的解析规则
     * @param serviceCode
     * @param indexName
     * @param logData
     */
    public  void    ranksSplittingIntegral(String  serviceCode,String indexName,String logData,Map<String,Object> indexMap){

             String  sql="SELECT   d.`target_index`,d.`data_index`,d.`data_end`,d.`data_key` ,d.`data_alias`,  r.`source_code`,r.rule_type, r.`rule_format`,r.`rule_pretty` FROM   `logger_rule_desc` d LEFT JOIN `logger_data_rule`  r ON d.`rule_id`=r.`rule_id`  WHERE r.`rule_flag`=1 and r.`source_code`=?  ORDER BY d.`desc_order`";
      //  List<SplittingIntegral> list =     jdbcTemplate.query(sql,new BeanPropertyRowMapper<SplittingIntegral>(),serviceCode);

              List<SplittingIntegral> list = jdbcTemplate.query(sql, new RowMapper<SplittingIntegral>() {
                  @Override
                  public SplittingIntegral mapRow(ResultSet resultSet, int i) throws SQLException {
                    //  logger.error("--获取封装方法---"+resultSet);
                       SplittingIntegral splittingIntegral=new SplittingIntegral();
                       splittingIntegral.setTargetIndex(resultSet.getString(1));
                      splittingIntegral.setDataIndex(resultSet.getInt(2));
                      splittingIntegral.setDataEnd(resultSet.getInt(3));
                      splittingIntegral.setDataKey(resultSet.getString(4));
                      splittingIntegral.setDataAlias(resultSet.getString(5));
                      splittingIntegral.setServiceCode(resultSet.getString(6));
                      splittingIntegral.setRuleType(resultSet.getInt(7));
                      splittingIntegral.setRuleFormat(resultSet.getString(8));
                      splittingIntegral.setRulePretty(resultSet.getString(9));
                 //     logger.error(splittingIntegral+"--获取封装方法---"+resultSet);
                      return splittingIntegral;
                  }
              },new Object[]{serviceCode});

              if(list.size()>=1){
                  for (SplittingIntegral integral:list){
                        logger.info("-------------当前解析数据为:"+integral);
                         if(integral.getRuleType()==1){
                        // 业务走的是智能切分   包含  字符串截取  字符分割    json格式解析
                            switch (integral.getRuleFormat()){
                                case "INTER":  //字符串截取业务判断
                                    if (logData.length()>integral.getDataEnd()){
                                        String  targetStr=    logData.substring(integral.getDataIndex(),integral.getDataEnd());
                                        indexMap.put(integral.getDataKey(),targetStr);
                                    }

                                    break;
                                case "SEPAR":  //字符串分隔符  业务处理
                                  String[]  intarry= logData.split(integral.getRulePretty());
                                       if(intarry.length>integral.getDataIndex()){
                                            String tempValue=intarry[integral.getDataIndex()];


                                          if(tempValue.indexOf("=")>=0){
                                              String[] tmparr=  intarry[integral.getDataIndex()].split("=");
                                              tempValue=tmparr[1].replaceAll("\"","");
                                           //   logtype="DB权限规则",clientip="192.168.9.108",clientport="25613",dbip="192.168.9.190",dbport="2003",dbtype="OSCAR",dbname="oscar_190",dbinstancename="OSRDB",dbencode="GB18030",dbusername="sysdba",applicationname="ISQL",connecttime="2019-11-15 10:25:30",recordtime="2019-11-15 10:30:45",result="监测",sql="select id,name from emp where name='test'"
                                          }
                                           indexMap.put(integral.getDataKey(),tempValue);
                                       }

                                    break;
                                case "JSON" :
                                     logData=JsonStringUtil.makeJsontoString(logData);
                                    if(JsonStringUtil.isJson(logData))  {
                                          Map mesMap = JSON.parseObject(logData, HashMap.class);
                                          if(integral.getDataAlias()!=null&&mesMap.containsKey(integral.getDataAlias())){
                                              indexMap.put(integral.getDataKey(),mesMap.get(integral.getDataAlias()));
                                          }
                                      }

                                    break;
                                    default:
                                   logger.info("-无法进入业务格式化-无效配置项"+integral);
                            }

                         }else if(integral.getRuleType()==0&&integral.getRuleFormat().equals("NOR")){
                             //自定义 正则表达式
                             //获取正则表达式内容
                             Pattern p =   Pattern.compile(integral.getRulePretty());
                             Matcher m=   p.matcher(logData);
                              boolean  f= m.find();
                              int valueNum=m.groupCount();
                             //符合业务
                             if(m.find(integral.getDataIndex())&&integral.getDataIndex()<valueNum){
                                 indexMap.put(integral.getDataKey(),m.group(integral.getDataIndex()));
                                 //试行计数器
                                 //indexMap.put("counter",Integer.parseInt(indexMap.getOrDefault("counter",0).toString())+1);
                                 }
                             }


                  }
                  logger.warn("*********************格式化解析数据规整："+indexMap);
                  if(indexMap.size()>=1){
                      try {
                          indexMap.put("timestamp",System.currentTimeMillis());//追加入库标准时间
                          long  snowId=snowFlake.nextId();




                          if(stringRedisTemplate.opsForHash().hasKey(CommonRediskey.machingRule,indexName)) {
                              logger.info("---判断是否符合 日志进一步加工业务流程"+CommonRediskey.machingRule+"----"+indexName);
                                indexMap.put("indexName",indexName); indexMap.put("id",snowId);
                              machingService.receiverMessage(indexMap);
                              logger.info("经过加工后数据 展示---:"+indexMap);
                          }
                            searchUtil.insertOrUpdateOne(indexName,snowId,indexMap);
                          /*********************加工后数据*****************************/
                          //获取日志等级字段值
                             String  leve= JsonStringUtil.checkLoggerLevel(logData);
                             if(leve!=null )
                          logAlarmNotification(0,leve, indexName, serviceCode, snowId);

                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                      logger.debug("实际中解析到目标日志：正则表达式中-------------完成业务清洗");
                  }







              }






    }












}
